"""
    DateAndTimeAndNanos(Clock)

Separate a Clock into CalendarDate, TimeOfDay,  Subseconds
                      in Days,      in Seconds, in Nanoseconds
"""
function DateAndTimeAndNanos(x::Clock)
    dt = Base.Dates.Date(x)
    no_subsecs = Nanoseconds(Seconds(x))
    tm = Base.Dates.Time(Nanosecond(value(no_subsecs)))
    nanosecs = Nanoseconds(x) - no_subsecs
    return dt, tm, nanosecs
end

function Base.string(x::Clock)
    dt, tm, nanosecs = DateAndTimeAndNanos(x)
    nanos = nanoseconds(nanosecs)
    nanostr = string(nanos)
    nanostr = string(ZEROCHARS[10-length(nanostr)], nanostr)
    if nanos != 0
        nanostr = string(DEC_SEP,nanostr)
        if endswith(nanostr, "000000")
            nanostr = nanostr[1:end-6]
        elseif endswith(nanostr, "000")
            nanostr = nanostr[1:end-3]
        end    
    else
        nanostr = ""
    end
    return string(dt, DTM_SEP, tm, nanostr)
end

function Base.string(x::UniversalTime, suffix::Char)
    return string(Clock(x), suffix)
end

function Base.string(x::LocalTime, ut2local::T) where T<:Union{Second, Seconds}    
    mins = div(ut2local.value, SECONDS_PER_MINUTE)
    offset = signed_hoursmins(mins)
    return string(Clock(x), offset)
end

function Base.string(x::UniversalTime, ut2local::T) where T<:Union{Second, Seconds}    
    mins = div(ut2local.value, SECONDS_PER_MINUTE)
    offset = signed_hoursmins(mins)
    return string(Clock(x), offset)
end

# settable subsecond precision

function Base.string(x::Clock, subsec_digits::Int)
    if signbit(subsec_digits) || subsec_digits > 9
        throw(ErrorException("Subseconds use 0..9 digits, not $(subsec_digits)"))
    end
    if subsec_digits > 0
        subsec_digits += mod(-subsec_digits, 3)
    end
    dt = Date(x)
    tm = Time24(x)
    tmstr = string(tm)
    if !contains(tmstr, ".") && subsec_digits>0
        tmstr = string(tmstr, '.', ZEROCHARS[subsec_digits+1])
    elseif subsec_digits == 0
        if contains(tmstr, ".")
            tmstr = split(tmstr,'.')[1]
        end
    else
        tmstrs = split(tmstr, '.')
        n = length(tmstrs[2])
        if n > subsec_digits
            tmstrs[2] = tmstrs[2][1:subsec_digits]
        elseif n < subsec_digits
            tmstrs[2] = string(tmstrs[2], ZEROCHARS[subsec_digits+1-length(tmstrs[2])])
        end
        tmstr = join(tmstrs, '.')
    end
    return string(dt, 'T', tmstr)
 end    

function Base.string(x::UniversalTime, subsec_digits::Int)
    result = string(Clock(x), subsec_digits)
    result = string(result, UTC_SFX)
    return result
end
    
function Base.string(x::LocalTime, subsec_digits::Int)
    result = string(Clock(x), subsec_digits)
    mins = div(UTM2LCL[1].value, SECONDS_PER_MINUTE)
    offset = signed_hoursmins(mins)
    result = string(result, offset)   
    return result
end
